//
//  RemoteStreamsGrid.swift
//  Hermes
//
//  Created by FH on 2021/1/17.
//  Copyright © 2021 Agora. All rights reserved.
//

import Foundation
// TODO: remove
// TODO: 使用GridVideosVC重构，之后增加全屏滚动显示及非全屏分页显示，支持大小流。大流不知道能不能用浮动window来实现
class RemoteStreamsComponent {
    private let appContext = HermesContext()
    private var height: CGFloat = 0
    private var width: CGFloat = 0
    private var hasInited = false
    private var gridCount = 0
    private var bgView = NSView()
    private var canvasItems: [VideoCanvasItem] = []
    private var yoga: FLContext! = nil
    
    init() {
        self.dataBinding()
    }
    
    private func dataBinding() {

    }
    
    func layoutViews(yoga: FLContext, windowSize: CGSize, _ superView: NSView) {
        if !self.hasInited {
            self.yoga = yoga
            self.height = windowSize.height - CGFloat(constScriptsInfoViewHeight +
                                                      constSettingsInfoViewHeight + constVerticalMarginDim +
                                                      constVerticalMarginDim +
                                                      constLoggerInfoViewHeight + constVerticalMarginDim * 2)
            self.width = windowSize.width - CGFloat(constHorizontalMarginDim * 3 +
                                                    constRemoteUsersPanelWidth + constLocalStreamPanelDim)
            
            self.bgView.bind(to: yoga, superView) { it in
                it.direction = .row
                it.wrap = .wrap
                it.width = self.width.toFLValue()
            }
            self.hasInited = true
        }
        self.layout()
    }
    
    private func layout() {
        if canvasItems.count > 0 {
            for item in canvasItems {
                yoga.removeNode(by: item.bgView)
            }
            self.canvasItems.removeAll()
        }

        let dim = calculateDim()
        for i in 0..<self.gridCount {
            let item = VideoCanvasItem()
            canvasItems.append(item)
            
            item.bgView = FLCommonView()
            item.bgView.bind(to: yoga, self.bgView) { it in
                it.marginLeft = constVideoItemMarginDim.toFLValue()
                it.marginBottom = constVideoItemMarginDim.toFLValue()
            }

            item.videoPanel = NSView()
            item.videoPanel.bind(to: yoga, item.bgView) { it in
                it.width = FLValue(dim)
                it.height = FLValue(dim)
                it.justify = .center
                it.alignItems = .center
            }
            item.videoPanel.flBackgroundColor = .lightGray

            item.lblIndex = FLLabel()
            item.lblIndex.bind(to: yoga, item.videoPanel)
            item.lblIndex.alignment = .center
            item.lblIndex.font = NSFont.systemFont(ofSize: 12)
            item.lblIndex.flText = "\(i+1)"
            
            item.lblUID = FLLabel()
            item.lblUID.bind(to: yoga, item.bgView) { it in
                it.width = FLValue(dim)
                it.flexGrow = 1
            }
            item.lblUID.font = NSFont.systemFont(ofSize: 10)
            item.lblUID.flText = "uid: ..."
            item.lblUID.flBackgroundColor = .gray

            item.coverView = NSView()
            item.coverView.flTag = 181818
            item.coverView.bind(to: yoga, item.bgView) { it in
                it.position = .absolute
                it.left = 0
                it.top = 0
                it.width = FLValue(dim)
                it.height = FLValue(dim)
            }
        }
    }
    
    private func calculateDim() -> CGFloat {
        let gridCount = self.gridCount
        let sizeWidth = self.width
        let sizeHeight = self.height
        let isMainAxisWidth = sizeWidth >= sizeHeight
        let mainAxisDim = isMainAxisWidth ? sizeWidth : sizeHeight
        let crossAxisDim = isMainAxisWidth ? sizeHeight : sizeWidth
        let mainAxisExtraDim = CGFloat(isMainAxisWidth
                                        ? constVideoItemMarginDim
                                        : (constRemoteUidHeight + constVideoItemMarginDim))
        let crossAxisExtraDim = CGFloat(isMainAxisWidth
                                        ? (constRemoteUidHeight + constVideoItemMarginDim)
                                        : constVideoItemMarginDim)
        if gridCount == 1 {
            let width = sizeWidth - mainAxisExtraDim
            let height = sizeHeight - crossAxisExtraDim
            return width > height ? height : width
        }
        
        let remainDim = mainAxisDim - crossAxisDim
        // row/column基本值
        let number = CGFloat(Int(sqrt(Double(gridCount))))
        // row/column会多出来的cell数量
        var addMoreNumber = CGFloat(Int(number * remainDim / crossAxisDim))
        
        var dim: CGFloat = 0
        var isDecrease = true
        while true {
            let currNum = number + addMoreNumber
            var currDim = (mainAxisDim - currNum * mainAxisExtraDim) / currNum
            // 四舍五入处理，防止cell数量太多时，因为dim小数部分累加后导致一行留空太多
            let integerDim = CGFloat(Int(currDim))
            var decimalDim = currDim - integerDim
            if decimalDim > 0.5 || decimalDim < 0.4 {
                decimalDim = CGFloat(floor(Double(decimalDim * 10)) / 10)
                currDim = integerDim + decimalDim
            } else if decimalDim >= 0.4 {
                currDim = integerDim + 0.35
            }
            let currCrossNum = CGFloat(Int(sizeHeight / (currDim + crossAxisExtraDim)))
            let currTotalNum = currNum * currCrossNum
            // 判断是要减少dim还是增加dim，以达到尽量填充width且不超出height的目的
            if currTotalNum >= CGFloat(gridCount) {
                dim = currDim
                if !isDecrease {
                    break
                }
            } else {
                if dim == 0 {
                    isDecrease = false
                }
                if isDecrease {
                    break
                }
            }
            if isDecrease {
                addMoreNumber -= 1
            } else {
                addMoreNumber += 1
            }
        }
        return dim
    }
}
